<template>
    <div id="three-3d"></div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import * as THREE from 'three'

let container = ref(null); // 页面元素
let camera = ref(null); // 摄像头
let scene = ref(null); // 场景
let grid = ref(null); // 地面坐标网格
let renderer = ref(null); // 渲染器
let cube = ref(null) // 正方体
let sphere = ref(null) // 球体
let light = ref(null) // 点光源
onMounted(() => {
    init()
})
// 该方法为初始化3D
function init() {
    //第一步，获取页面元素 将来渲染的画面将会显示在 id为 three-3d 的<div></div>中
    container = document.getElementById("three-3d");
    //第二步，初始化场景
    scene = new THREE.Scene();
    // 第三步，初始化摄像头
    // 3.1 初始化摄像头，后续参数为依次视角、画面的长宽比、近视距离、远视距离
    camera = new THREE.PerspectiveCamera( 45, container.clientWidth / container.clientHeight, 0.1, 200000);
    // 3.2设置摄像头坐标
    camera.position.set(0 ,10, 10);
    // 设置摄像头方向
    camera.lookAt(new THREE.Vector3(0,0,0));

    // 第四步，初始化地面坐标网格 
    // 4.1 参数： 大小， 分隔数量， 坐标系颜色， 坐标系辅助线颜色
    grid = new THREE.GridHelper(1000, 1000, 0x000000, 0x999999);
    // 4.2 坐标系材料是否可以透明，为了避免网格阻挡其他的模型，所以设置一下地面的透明度
    grid.material.transparent = true;
    // 4.3 坐标系材料透明度，
    grid.material.opacity = 0.8;
    grid.receiveShadow = true
    // 4.4 将这个画面设置到场景中
    scene.add(grid);

    //第五步， 初始化渲染器
    renderer = new THREE.WebGLRenderer({
        antialias: true, // 是否抗锯齿
        alpha: true, // 清除alpha值
        precision: "highp" // 着色器精度
    });

    // 新建几何体，参数长(x轴方向)，宽(y轴方向)，高(z轴方向)
    let cubeGeometry = new THREE.BoxGeometry( 2, 2, 2 );
    // 新建网格材质
    let cubeMaterial = new THREE.MeshLambertMaterial( {color: 0xffffff} );
    // 形成几何体网格
    cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
    // 设置几何体网络的坐标
    cube.position.set(0,1,0)
    // 接收阴影
    cube.receiveShadow = true
    // 开启阴影渲染
    cube.castShadow = true
    // 将几何体加入场景中
    scene.add( cube );

    // 新建几何体，参数球体半径， 横向的分段数， 纵向分段数
    let sphereGeometry = new THREE.SphereGeometry( 1, 32, 16 );
    // 新建球体材质
    let sphereMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff } );
    // 形成几何体网格
    sphere = new THREE.Mesh( sphereGeometry, sphereMaterial );
    // 设置几何体网络的坐标
    sphere.position.set(0,3,0)

    // 接收阴影
    sphere.castShadow = true
    // 接收阴影
    sphere.receiveShadow = true

    // 将几何体加入场景中
    scene.add( sphere );

    // 初始化点光源，参数光源颜色，光照强度，光源消失距离（0代表不会消失）
    light = new THREE.PointLight( 0xffffff, 10, 0 );
    // 光源位置
    light.position.set( 10, 3, 10 );
    // 开启阴影渲染
    light.castShadow = true;
    // 将光源加入场景中
    scene.add( light );

    // 5.2 渲染器大小
    renderer.setSize(container.clientWidth, container.clientHeight);
    // 5.3 引入场景和摄像头开始渲染
    renderer.render(scene, camera);
    // 开启阴影
    renderer.shadowMap.enabled = true;
    // 5.4 将渲染出的canvas填充到相应元素中
    container.appendChild(renderer.domElement)
}
</script>
<style scoped>
    #three-3d{
        width: 100vw;
        height: 100vh;
    }
</style>